/*
 * $Id: Thread.h,v 1.10 2006-04-03 10:40:26 bacon Exp $
 */

#ifndef _XPP_BAS_THREAD_CLASS_
#define _XPP_BAS_THREAD_CLASS_

#include <xp/bas/thr.h>
#include <xp/bas/time.h>
#include <xpp/Uncopyable.h>
#include <xpp/bas/Runnable.h>

/*
 * CLASS: xpp::bas::Thread
 *   Encaptulates the system thread.
 * 
 * EXAMPLE:
 */

namespace xpp
{
	namespace bas
	{

		class Thread: protected xp_thr_t, public Uncopyable, public Runnable
		{
		public:
			/*
			 * TYPE: Handle
			 *   Defines the cross-platform wrapper type for the native thread
			 */
			typedef xp_thrhnd_t Handle;
			
			enum
			{
				INCUBATING = XP_THR_INCUBATING,
				RUNNING    = XP_THR_RUNNING,
				TERMINATED = XP_THR_TERMINATED,
				ABORTED    = XP_THR_ABORTED
			};

			enum
			{
				DETACHED    = XP_THR_DETACHED
			};

			/* 
			 * CONSTRUCTOR: Thread
			 */
			Thread ();

			/* 
			 * DESTRUCTOR: ~Thread
			 */
			virtual ~Thread ();
			
			/*
			 * METHOD: handle
			 *   Returns the internal handle to the thread
			 */	
			Handle handle () const
			{
				return this->__handle;
			}

			static Handle current ();
			
			/* 
			 * METHOD: state
			 *   Returns the thread state
			 *		
			 * RETURNS:
			 *   - XP_THREAD_INCUBATING
			 *   - XP_THREAD_RUNNING
			 *   - XP_THREAD_TERMINATED
			 *   - XP_THREAD_ABORTED
			 */
			int state () const
			{
				return this->__state;
			}

			/*
 			 * METHOD: returnCode
 			 *   Returns the return code of the main thread routine
			 */
			int returnCode () const
			{
				return this->__return_code;
			}

			Runnable* target (void) const
			{
				return thread_target;
			}

			void setTarget (Runnable* target)
			{
				thread_target = target;
			}

			/*
			 * METHOD: start
			 *   Starts the thread
			 *
			 * PARAMETERS:
			 *   flags - 0 for none, XP_THREAD_DETACHED to detach 
                         *           the thread upon start-up
			 *
			 * RETURNS:
			 *   0 on success, -1 on failure
			 */
			virtual int start (int flags = 0);

			/*
			 * METHOD: stop
			 *   Stops the thread
			 *
			 * RETURNS:
			 *   0 on success, -1 on failure
			 *
			 * REMARKS:
			 *   <stop> must be overridden by the subclass as 
			 *   it would just abort the thread by itself.
			 */
			virtual int stop ();

			/*
			 * METHOD: join
			 */
			int join ()
			{
				return xp_thr_join (this);
			}

			/*
			 * METHOD: detach
			 */
			int detach ()
			{
				return xp_thr_detach (this);
			}

			/*
			 * METHOD: sleep
			 *   Suspends the thread
			 *
			 * PARAMETERS:
			 *   msecs - milliseconds to suspends the thread for 
			 */
			void sleep (xp_time_t msecs)
			{
				xp_sleep (msecs);
			}

			/*
			 * METHOD: kill
			 *   Sends a signal to the thread
			 *
			 * PARAMETERS:
			 *   sig - signal number to send
			 */
			int kill (int sig)
			{
				return xp_thr_kill (this, sig);
			}

			int blockSignal (int sig)
			{
				return xp_thr_blocksig (this, sig);
			}

			int unblockSignal (int sig)
			{
				return xp_thr_unblocksig (this, sig);
			}

			int blockAllSignals ()
			{
				return xp_thr_blockallsigs (this);
			}

			int unblockAllSignals ()
			{
				return xp_thr_unblockallsigs (this);
			}

		protected:
			Runnable* thread_target;

			int create_thread ();
			static void* start_thread (void*);

			static Handle INVALID_HANDLE;
		};

	}
}

#endif
